﻿
using Propro.LogWriter;
using Propro.Models;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity.Validation;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using PagedList;


namespace Propro.Controllers
{
    public class ProjectsController : Controller
    {
        private ProWebContext _db = new ProWebContext();

        public ActionResult List(String searchTerm = null, int page = 1)
        {

            var model = _db.Projects
                .Where(p => searchTerm == null || p.Name.Contains(searchTerm)).OrderBy(p => p.Name).ToPagedList(page, 10);

            if(Request.IsAjaxRequest())
            {
                return PartialView("_Projects", model);
            }

            return View(model);
        }

        public ActionResult Details(int id)
        {
            Project pro = _db.Projects.Find(id);
            return View(pro);
        }

        public ActionResult Delete(int id)
        {
            Project pro = _db.Projects.Find(id);
            return View(pro);
        }

        public ActionResult Edit(int id)
        {
            Project pro = _db.Projects.Find(id);
            if (User.IsInRole("Project" + pro.ProjectId))
                return View(pro);
            else
            {
                /*logging*/
                LoggerWriter.log(Enum.LogSoort.error, "user not in role", User.Identity.Name);
                /*logging*/
                return RedirectToAction("List");
            }
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Exclude = "CreationDate")] Project project)
        {

            if (!User.IsInRole("Project" + project.ProjectId))
            {
                /*logging*/
                LoggerWriter.log(Enum.LogSoort.error, "user not in role", User.Identity.Name);
                /*logging*/
                return RedirectToAction("List");
            }

            var origPro = _db.Projects.Find(project.ProjectId);
            if (origPro == null)
            {
                return HttpNotFound();
            }

            if (ModelState.IsValid)
            {
                origPro.Name = project.Name;
                origPro.ShortDescription = project.ShortDescription;
                origPro.Description = project.Description;
                _db.SaveChanges();

                /*logging*/
                LoggerWriter.log(Enum.LogSoort.update, origPro.Name, User.Identity.Name);
                /*logging*/

                return RedirectToAction("Details", new { id = origPro.ProjectId });
            }

            return View(origPro);

        }

        public ActionResult getUpdates(int id)
        {
            Project pro = _db.Projects.Find(id);
            return PartialView("_getUpdates", pro);
        }

        public ActionResult getDownloads(int id)
        {
            Project pro = _db.Projects.Find(id);
            return PartialView("_getDownloads", pro);
        }

        public ActionResult getMembers(int id)
        {
            Project pro = _db.Projects.Find(id);

            var memberLists = new addMember();
            memberLists.Members = pro.Members;
            var memberIds = pro.Members.Select(m => m.UserId).ToArray();

            memberLists.NotMembers = (from u in _db.Users
                                      where !(memberIds.Contains(u.UserId))
                                      select u).ToList();

            memberLists.ProjectId = pro.ProjectId;

            return PartialView("_getMembers", memberLists);
        }

        /* Updates section */
        public ActionResult editUpdate(int id)
        {

            Updates update = _db.Updates.Find(id);

            if (!User.IsInRole("Project" + update.Project.ProjectId))
            {
                /*logging*/
                LoggerWriter.log(Enum.LogSoort.error, "user not in role", User.Identity.Name);
                /*logging*/
                return RedirectToAction("List");
            }

            updateEdit ori = new updateEdit();
            ori.Content = update.Content;
            ori.UpdateId = update.UpdateId;

            return View(ori);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult editUpdate(updateEdit upd)
        {
            var original = _db.Updates.Find(upd.UpdateId);
            if (!User.IsInRole("Project" + original.Project.ProjectId))
            {
                /*logging*/
                LoggerWriter.log(Enum.LogSoort.error, "user not in role", User.Identity.Name);
                /*logging*/
                return RedirectToAction("List");
            }

            if (ModelState.IsValid)
            {
                original.Content = upd.Content;
                original.User = original.User;
                _db.Entry(original).Property(u => u.Content).IsModified = true;
                _db.SaveChanges();
                
                /*logging*/
                LoggerWriter.log(Enum.LogSoort.update, "edit update: " + upd.Content, User.Identity.Name);
                /*logging*/

                return RedirectToAction("Details", new { id = original.Project.ProjectId });

            }

            return View(upd);
        }

        public ActionResult deleteUpdate(int id)
        {
            var update = _db.Updates.Find(id);
            if (!User.IsInRole("Project" + update.Project.ProjectId))
            {
                /*logging*/
                LoggerWriter.log(Enum.LogSoort.error, "user not in role", User.Identity.Name);
                /*logging*/
                return RedirectToAction("List");
            }

            return View(update);
        }

        [HttpPost]
        public ActionResult deleteUpdate(int id, Updates toDel)
        {
            var original = _db.Updates.Find(id);
            if (!User.IsInRole("Project" + original.Project.ProjectId))
            {
                /*logging*/
                LoggerWriter.log(Enum.LogSoort.error, "user not in role", User.Identity.Name);
                /*logging*/
                return RedirectToAction("List");
            }

            int project = original.Project.ProjectId;

            _db.Updates.Remove(original);
            _db.SaveChanges();

            /*logging*/
            LoggerWriter.log(Enum.LogSoort.delete, " delete update " + original.UpdateId  , User.Identity.Name);
            /*logging*/

            return RedirectToAction("Details", new { id = project });
        }

        public ActionResult addUpdate(int ProjectId)
        {
            if (!User.IsInRole("Project" + ProjectId))
            {
                /*logging*/
                LoggerWriter.log(Enum.LogSoort.error, "user not in role", User.Identity.Name);
                /*logging*/
                return RedirectToAction("List");
            }

            addUpdate temp = new addUpdate();
            temp.Project = ProjectId;

            return View(temp);
        }

        [HttpPost]
        public ActionResult addUpdate(addUpdate toAdd)
        {
            if (!User.IsInRole("Project" + toAdd.Project))
            {
                /*logging*/
                LoggerWriter.log(Enum.LogSoort.error, "user not in role", User.Identity.Name);
                /*logging*/
                return RedirectToAction("List");
            }

            Updates insert = new Updates();
            insert.Content = toAdd.Content;
            insert.Project = _db.Projects.Find(toAdd.Project);
            insert.User = _db.Users.Where(u => u.UserName == User.Identity.Name).First();
            insert.Date = DateTime.Now;
            _db.Updates.Add(insert);
            _db.SaveChanges();

            /*logging*/
            LoggerWriter.log(Enum.LogSoort.insert, "add update" + toAdd.Content, User.Identity.Name);
            /*logging*/


            return RedirectToAction("Details", new { id = toAdd.Project });
        }

        /* Downloads section */
        public ActionResult editDownload(int id)
        {
            Downloads down = _db.Downloads.Find(id);

            if (!User.IsInRole("Project" + down.Project.ProjectId))
            {
                /*logging*/
                LoggerWriter.log(Enum.LogSoort.error, "user not in role", User.Identity.Name);
                /*logging*/
                return RedirectToAction("List");
            }


            editDownload ori = new editDownload();
            ori.Description = down.Description;
            ori.DowloadID = down.DowloadID;

            return View(ori);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult editDownload(editDownload upd)
        {
            var original = _db.Downloads.Find(upd.DowloadID);
            if (!User.IsInRole("Project" + original.Project.ProjectId))
            {
                /*logging*/
                
                LoggerWriter.log(Enum.LogSoort.error, "user not in role", User.Identity.Name);
                /*logging*/
                return RedirectToAction("List");
            }

            if (ModelState.IsValid)
            {

                if (upd.file != null)
                {
                    if (upd.file.ContentLength > 0)
                    {
                        var fileName = Path.GetFileName(upd.file.FileName);
                        var path = Path.Combine(Server.MapPath("~/downloads"), fileName);
                        upd.file.SaveAs(path);
                        original.Link = fileName;

                        /*logging*/
                        LoggerWriter.log(Enum.LogSoort.update, "edit download" + path + ", " + fileName, User.Identity.Name);
                        /*logging*/
                    }
                }
                original.Description = upd.Description;
                _db.Entry(original).Property(d => d.Description).IsModified = true;
                _db.Entry(original).Property(d => d.Link).IsModified = true;
                _db.SaveChanges();
                return RedirectToAction("Details", new { id = original.Project.ProjectId });
            }


            return View(upd);
        }

        public ActionResult Download(int downloadId)
        {
            Downloads down = _db.Downloads.Find(downloadId);

            Response.AddHeader("Content-Disposition", @"filename=" + down.Link + "");
            return File(Path.Combine(Server.MapPath("~/downloads"), down.Link), "application/text");
        }

        public ActionResult deleteDownload(int downloadId)
        {
            var down = _db.Downloads.Find(downloadId);

            if (!User.IsInRole("Project" + down.Project.ProjectId))
            {
                /*logging*/
                
                LoggerWriter.log(Enum.LogSoort.error, "user not in role", User.Identity.Name);
                /*logging*/
                return RedirectToAction("List");
            }


            return View(down);
        }

        [HttpPost]
        public ActionResult deleteDownload(int downloadId, Downloads down)
        {
            var original = _db.Downloads.Find(downloadId);
            if (!User.IsInRole("Project" + original.Project.ProjectId))
            {
                /*logging*/
                
                LoggerWriter.log(Enum.LogSoort.error, "user not in role", User.Identity.Name);
                /*logging*/
                return RedirectToAction("List");
            }

            int project = original.Project.ProjectId;

            _db.Downloads.Remove(original);
            _db.SaveChanges();

            /*logging*/
            LoggerWriter.log(Enum.LogSoort.delete, "delete download" + original.DowloadID, User.Identity.Name);
            /*logging*/

            return RedirectToAction("Details", new { id = project });
        }

        public ActionResult addDownload(int projectId)
        {
            if (!User.IsInRole("Project" + projectId))
            {
                /*logging*/
                
                LoggerWriter.log(Enum.LogSoort.error, "user not in role", User.Identity.Name);
                /*logging*/
                return RedirectToAction("List");
            }

            var newDown = new addDownload();
            newDown.ProjectId = projectId;

            return View(newDown);
        }

        [HttpPost]
        public ActionResult addDownload(addDownload toAdd)
        {
            if (!User.IsInRole("Project" + toAdd.ProjectId))
            {
                /*logging*/
                
                LoggerWriter.log(Enum.LogSoort.error, "user not in role", User.Identity.Name);
                /*logging*/
                return RedirectToAction("List");
            }


            if (ModelState.IsValid)
            {

                var insert = new Downloads();
                insert.Description = toAdd.Description;
                insert.Project = _db.Projects.Find(toAdd.ProjectId);
                insert.date = DateTime.Now;

                if (toAdd.file != null)
                {
                    if (toAdd.file.ContentLength > 0)
                    {
                        var fileName = Path.GetFileName(toAdd.file.FileName);
                        var path = Path.Combine(Server.MapPath("~/downloads"), fileName);
                        toAdd.file.SaveAs(path);
                        insert.Link = fileName;
                    }
                    _db.Downloads.Add(insert);
                    _db.SaveChanges();

                    /*logging*/
                    LoggerWriter.log(Enum.LogSoort.insert, "insert download " + insert.DowloadID, User.Identity.Name);
                    /*logging*/
                }
                else
                {
                    return View(toAdd);
                }
            }
            


            return RedirectToAction("Details", new { id = toAdd.ProjectId });
        }

        /*Projects section*/
        public ActionResult addProject()
        {
            var addpro = new addProject();
            return View(addpro);
        }

        [HttpPost]
        public ActionResult addProject(addProject toAdd)
        {

            if (!User.Identity.IsAuthenticated)
            {
                /*logging*/
                LoggerWriter.log(Enum.LogSoort.error, "user not in role", User.Identity.Name);
                /*logging*/
                return RedirectToAction("List");
            }

            if (ModelState.IsValid)
            {

                Project insert = new Project();
                insert.Description = toAdd.Description;
                insert.ShortDescription = toAdd.ShortDescription;
                insert.CreationDate = DateTime.Now;

                MembershipUser CurrentUser = Membership.GetUser(User.Identity.Name);

                insert.Members.Add(_db.Users.Find(CurrentUser.ProviderUserKey));
                insert.Name = toAdd.Name;
                _db.Projects.Add(insert);
                _db.SaveChanges();

                int id = insert.ProjectId;
                Roles.CreateRole("Project" + id);
                Roles.AddUserToRole(User.Identity.Name, "Project" + id);

                /*logging*/
                LoggerWriter.log(Enum.LogSoort.insert, "add project " + insert.ProjectId, User.Identity.Name);
                /*logging/*/

            }
            else
            {
                return View(toAdd);
            }

            return RedirectToAction("List");
        }

        /* members section */
        public ActionResult addMember(int SelectedMemberId, int ProjectId)
        {
            if (!User.IsInRole("Project" + ProjectId))
            {
                /*logging*/
                
                LoggerWriter.log(Enum.LogSoort.error, "user not in role", User.Identity.Name);
                /*logging*/
                return RedirectToAction("List");
            }

            UserProfile member = _db.Users.Find(SelectedMemberId);
            Roles.AddUserToRole(member.UserName, "Project" + ProjectId);

            _db.Projects.Find(ProjectId).Members.Add(member);
            _db.SaveChanges();

            /*logging*/
            LoggerWriter.log(Enum.LogSoort.insert, " added member" +member.UserName+ " to project" + ProjectId, User.Identity.Name);
            /*logging*/

            return RedirectToAction("Details", new { id = ProjectId });
        }

        public ActionResult leaveProject(int ProjectId)
        {
            if (!User.IsInRole("Project" + ProjectId))
            {
                /*logging*/
                
                LoggerWriter.log(Enum.LogSoort.error, "user not in role", User.Identity.Name);
                /*logging*/
                return RedirectToAction("List");
            }

            Roles.RemoveUserFromRole(User.Identity.Name, "Project" + ProjectId);
            UserProfile toRemove = _db.Users.Where(u => u.UserName.Equals(User.Identity.Name)).First();

            _db.Projects.Find(ProjectId).Members.Remove(toRemove);
            _db.SaveChanges();

            /*logging*/
            LoggerWriter.log(Enum.LogSoort.delete, " user " + User.Identity.Name + " left project " + _db.Projects.Find(ProjectId).ProjectId, User.Identity.Name);
            /*logging*/

            return RedirectToAction("Details", new { id = ProjectId });
        }


        protected override void Dispose(bool disposing)
        {
            if (_db != null)
            {
                _db.Dispose();
            }

            base.Dispose(disposing);
        }
    }
}
